<template>
  <div class="deepchat-container-box">
    <div class="deepchat-container">
      <!-- 第一列：功能导航 -->
      <div class="sidebar">
        <sidebar :unread-count="unreadCount" :current-tab="activeTab" @select-tab="handleSelectTab" />
      </div>

      <!-- 第二列：聊天/联系人列表 -->
      <div class="list-container">
        <chat-list v-if="activeTab == 'chat'" :chat-list="filteredChats" :active-chat="activeChatId"
          @select-chat="handleSelectChat" />
        <contact-list v-else-if="activeTab == 'contact'" :contact-list="filteredContacts"
          :active-contact="selectedContact?.id" @select-contact="handleSelectContact" @select-chat="startNewChat" />
      </div>

      <!-- 第三列：聊天窗口 -->
      <div class="chat-container">
        <chat-window v-if="activeChat" :chat="activeChat" @send-message="handleSendMessage"
          @start-call="handleStartCall" />
        <el-card v-else-if="selectedContact" style="min-height: 480px">
          <div class="contact-detail">
            <div class="contact-header">
              <el-avatar :size="120" :src="selectedContact.avatar" />
            </div>
            <div class="contact-info">
              <el-row>
                <el-col :span="24">昵称: {{ selectedContact.nickname }}</el-col>
              </el-row>
              <el-row>
                <el-col :span="24">备注: {{ selectedContact.remark }}</el-col>
              </el-row>
              <el-row>
                <el-col :span="24">手机: {{ selectedContact.phone }}</el-col>
              </el-row>
              <el-row>
                <el-col :span="24">性别: {{
                  selectedContact.gender == 1 ? "男" :
                    selectedContact.gender == 2 ? "女" : "未知"
                }}</el-col>
              </el-row>
              <el-row>
                <el-col :span="4">
                  签名:
                </el-col>
                <el-col :span="20">
                  <el-input v-model="selectedContact.signature" :rows="2" type="textarea" disabled />
                </el-col>
              </el-row>
            </div>
          </div>
          <div class="contact-actions">
            <el-button type="primary" @click="startChatWithContact">发送消息</el-button>
            <el-button type="danger" @click="deleteContact">删除好友</el-button>
          </div>
        </el-card>

        <div v-else class="empty-chat">
          <el-empty description="请选择聊天" />
        </div>
      </div>
    </div>

    <!-- 通话组件 -->
    <call v-if="showCall" ref="callRef" :showCall="showCall" :call-type="callType" :call-with="callWith"
      :is-caller="isCaller" @end-call="handleEndCall" @send-signal="handleSignalMessage" />
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, watch } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import Sidebar from "@/components/Sidebar.vue";
import ChatList from "@/components/ChatList.vue";
import ContactList from "@/components/ContactList.vue";
import ChatWindow from "@/components/ChatWindow.vue";
import Call from "@/components/Call.vue";
import { useChatStore } from "@/stores/chat";
import { useUserStore } from "@/stores/user";
import { getFriends } from "@/api/friends";
import { sendMessage, getChatHistory } from "@/api/message";

const userStore = useUserStore();

// 状态管理
const activeTab = ref("chat");
const activeChatId = ref(null);
const { chatList, getChatList, addChatList, clearChatList } = useChatStore();
const contactList = ref([]);
const selectedContact = ref(null);
const searchText = ref("");
const showCall = ref(false);
const callType = ref("");
const callWith = ref("");
const isCaller = ref(false);
const callRef = ref(null)

const socket = ref(null);
const isConnected = ref(false);
const reconnectAttempts = ref(0);
const maxReconnectAttempts = 5;
const reconnectDelay = 3000; // 3秒重连间隔

// 计算属性
const activeChat = computed(() => chatList.value.find(chat => chat.id == activeChatId.value));
const filteredChats = computed(() => filterItems(chatList.value, searchText.value));
const filteredContacts = computed(() => filterItems(contactList.value, searchText.value));

const handleSelectTab = (tab) => {
  activeTab.value = tab;
  if (tab !== "chat") {
    activeChatId.value = null;
    selectedContact.value = null;
  } else if (tab === "chat") {
    const chatId = chatList.value[0].id;
    handleSelectChat(chatId)
  }
};

const handleSelectChat = (chatId) => {
  activeChatId.value = chatId;
  selectedContact.value = null;
  const chat = chatList.value.find(c => c.id == chatId);
  if (chat) {
    chat.unread = 0;
    loadHistoryMessages(chatId); // 加载历史消息
  }
};

const handleSelectContact = (contact) => {
  selectedContact.value = contact;
  activeChatId.value = null;
};

const startChatWithContact = async () => {
  if (!selectedContact.value) return;

  let chat = chatList.value.find(c => c.id == selectedContact.value.id);
  if (!chat) {
    chat = {
      ...selectedContact.value,
      unread: 0,
      messages: [],
    };
  }

  await addChatList(chat)

  activeChatId.value = selectedContact.value.id;
  selectedContact.value = null;
  handleSelectTab('chat');
};

const deleteContact = async () => {
  if (!selectedContact.value) return;

  try {
    await ElMessageBox.confirm(
      `确定要删除好友 ${selectedContact.value.remark || selectedContact.value.nickname} 吗?`,
      "删除好友",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }
    );

    // 这里调用API删除好友
    // await deleteFriend(selectedContact.value.id);

    // 从联系人列表和聊天列表中移除
    contactList.value = contactList.value.filter(c => c.id !== selectedContact.value.id);
    chatList.value = chatList.value.filter(c => c.id !== selectedContact.value.id);

    ElMessage.success("删除好友成功");
    selectedContact.value = null;
    if (activeChatId.value == selectedContact.value.id) {
      activeChatId.value = null;
    }
  } catch (error) {
    console.log("取消删除");
  }
};

// WebSocket连接
const initWebSocket = () => {
  const userId = userStore.userInfo?.id;
  if (!userId) return;

  const wsProtocol = window.location.protocol == "https:" ? "wss://" : "ws://";
  const wsUrl = `${wsProtocol}${window.location.hostname}:8080/websocket/${userId}`;
  console.log("WebSocket connecting to:", wsUrl);

  socket.value = new WebSocket(wsUrl);

  socket.value.onopen = () => {
    console.log("WebSocket connected");
    isConnected.value = true;
    reconnectAttempts.value = 0;
    startHeartbeat();
  };

  socket.value.onmessage = (event) => {
    try {
      const message = JSON.parse(event.data);
      handleWebSocketMessage(message);
    } catch (error) {
      console.error("Failed to parse message", error);
    }
  };

  socket.value.onclose = (event) => {
    console.log("WebSocket disconnected", event);
    isConnected.value = false;
    stopHeartbeat();

    // 非正常关闭时尝试重连
    if (event.code !== 1000 && reconnectAttempts.value < maxReconnectAttempts) {
      setTimeout(() => {
        reconnectAttempts.value++;
        console.log(`Attempting to reconnect (${reconnectAttempts.value}/${maxReconnectAttempts})`);
        initWebSocket();
      }, reconnectDelay);
    }
  };

  socket.value.onerror = (error) => {
    console.error("WebSocket error", error);
    isConnected.value = false;
  };
};

// 心跳机制
let heartbeatInterval;
const startHeartbeat = () => {
  heartbeatInterval = setInterval(() => {
    if (socket.value?.readyState == WebSocket.OPEN) {
      socket.value.send(JSON.stringify({ type: "heartbeat" }));
    }
  }, 30000);
};

const stopHeartbeat = () => {
  if (heartbeatInterval) clearInterval(heartbeatInterval);
};

// 方法
const filterItems = (items, search) => {
  if (!search) return items;
  return items.filter(item =>
    item.name.toLowerCase().includes(search.toLowerCase()) ||
    (item.lastMessage && item.lastMessage.toLowerCase().includes(search.toLowerCase())
    ))
};

// 消息处理
const handleWebSocketMessage = (message) => {
  console.log('Received message:', message);
  switch (message.type) {
    case "single":
      handleSingleMessage(message);
      break;
    case "call":
      console.log('Call request:', message.callType);
      handleCallRequest(message);
      break;
    case "call_response":
      console.log('Call response:', message.response, message.callType);
      handleCallResponse(message);
      break;
    case "status":
      handleUserStatus(message);
      break;
    case "allUserStatus":
      handleAllUserStatus(message);
      break;
    case "call_reconnect":
      if (!showCall.value) {
        showCall.value = true;
        callType.value = message.callType;
        callWith.value = message.fromId;
        isCaller.value = false;
      }
      break;
    case "call_end":
      handleRemoteCallEnd(message)
      break
    case "call_offer":
      if (callRef.value) {
        callRef.value.handleRemoteOffer(message.sdp)
      }
      break
    case "call_answer":
      if (callRef.value) {
        callRef.value.handleRemoteAnswer(message.sdp)
      }
      break
    case "call_ice_candidate":
      if (callRef.value) {
        callRef.value.handleRemoteCandidate(message.candidate)
      }
      break
    default:
      console.warn("Unknown message type:", message.type);
  }
};

const handleSignalMessage = (signalData) => {
  sendWebSocketMessage({
    type: signalMessageType(signalData.type),
    toId: callWith.value,
    ...signalData
  })
}

const signalMessageType = (type) => {
  switch (type) {
    case 'offer': return 'call_offer'
    case 'answer': return 'call_answer'
    case 'ice-candidate': return 'call_ice_candidate'
    default: return type
  }
}

const handleSingleMessage = (message) => {
  const { fromId, messageType } = message;
  let chat = chatList.value.find(c => c.id == fromId);

  if (!chat) {
    chat = createNewChat(fromId);
    if (!chat) return;
  }

  const receivedMsg = {
    id: `msg-${Date.now()}`,
    isMe: false,
    type: messageType,
    content: message.content,
    time: new Date(),
    status: 'received'
  };

  // 处理不同类型消息
  if (messageType == 'file') {
    receivedMsg.fileName = message.fileName;
    receivedMsg.fileSize = message.fileSize;
  } else if (messageType == 'audio') {
    receivedMsg.duration = message.duration;
  } else if (messageType == 'call') {
    receivedMsg.callType = message.callType;
    receivedMsg.duration = message.duration;
  }

  chat.messages.push(receivedMsg);
  if (activeChatId.value !== fromId) chat.unread++;
};
const handleCallRequest = async (message) => {
  const { fromId, type } = message;

  try {
    await ElMessageBox.confirm(
      `收到${type === 'video' ? '视频' : '语音'}通话请求，是否接受？`,
      "通话请求",
      {
        confirmButtonText: "接受",
        cancelButtonText: "拒绝",
        type: "info",
      }
    );

    // 用户接受通话
    showCall.value = true;
    callType.value = type;
    callWith.value = fromId;
    isCaller.value = false;

    // 发送接受响应
    await sendWebSocketMessage({
      type: "call_response",
      toId: fromId,
      response: "accept",
      callType: type
    });

    // 添加到聊天记录（仅一次）
    addCallMessage(fromId, type, false, 'accepted');
  } catch {
    // 用户拒绝通话
    await sendWebSocketMessage({
      type: "call_response",
      toId: fromId,
      response: "reject",
      callType: type
    });
    addCallMessage(fromId, type, false, 'rejected');
  }
};

const handleRemoteCallEnd = (message) => {
  // 只有当前正在通话中才处理
  if (showCall.value && callWith.value == message.fromId) {
    // 主动清除通话状态
    showCall.value = false
    callType.value = ""
    callWith.value = ""
    isCaller.value = false

    // 调用 Call.vue 的 endCall 方法，强制关闭媒体设备
    if (callRef.value && callRef.value.endCall) {
      callRef.value.endCall()
    }

    // 添加通话记录
    const chat = chatList.value.find(c => c.id == message.fromId)
    if (chat) {
      const now = Date.now()

      const existingCall = chat.messages.some(msg =>
        msg.type === 'call' &&
        msg.callType === message.callType &&
        Math.abs(new Date(msg.time) - now) < 1000
      )

      // 添加通话结束记录
      if (!existingCall) {
        chat.messages.push({
          id: `call-end-${Date.now()}`,
          isMe: false,
          type: 'call',
          callType: message.callType,
          duration: message.duration,
          time: new Date(),
          status: message.duration > 0 ? 'ended' : 'missed'
        })
      }
    }
  }
}

// 记录通话消息
const addCallMessage = (userId, type, isOutgoing, status) => {
  const chat = chatList.value.find(c => c.id == userId)
  if (!chat) return

  const now = Date.now()

  const existingCall = chat.messages.some(msg => {
    return (
      msg.type === 'call' &&
      msg.callType === type &&
      Math.abs(new Date(msg.time) - now) < 1000 // 缩短为5秒内避免重复
    )
  })

  if (!existingCall) {
    chat.messages.push({
      id: `call-${Date.now()}`,
      isMe: isOutgoing,
      type: 'call',
      callType: type,
      time: new Date(),
      status: status === 'accepted' ? 'connected' :
        status === 'rejected' ? 'rejected' : 'missed',
      duration: status === 'accepted' ? 0 : undefined
    })
  }
}

const handleCallResponse = (message) => {
  if (message.response === "accept") {
    showCall.value = true;
    callType.value = message.callType;
    callWith.value = message.fromId;
    isCaller.value = true;

    // 更新通话状态为已接听，并添加记录
    addCallMessage(message.fromId, message.callType, true, 'accepted');
  } else {
    showCall.value = false;
    ElMessage.warning("对方已拒绝通话请求");
    addCallMessage(message.fromId, message.callType, true, 'rejected');
  }
};

// 保存通话状态
const saveCallState = () => {
  if (showCall.value) {
    sessionStorage.setItem('activeCall', JSON.stringify({
      type: callType.value,
      with: callWith.value,
      isCaller: isCaller.value,
      timestamp: Date.now()
    }));
  } else {
    sessionStorage.removeItem('activeCall');
  }
};

// 恢复通话状态
const restoreCallState = () => {
  const savedCall = sessionStorage.getItem('activeCall');
  if (savedCall) {
    const { type, with: withId, isCaller: caller, timestamp } = JSON.parse(savedCall);

    // 只恢复5分钟内的通话
    if (Date.now() - timestamp < 5 * 60 * 1000) {
      showCall.value = true;
      callType.value = type;
      callWith.value = withId;
      isCaller.value = caller;

      // 通知对方恢复通话
      if (caller) {
        sendWebSocketMessage({
          type: "call_reconnect",
          toId: withId,
          callType: type
        });
      }
    } else {
      sessionStorage.removeItem('activeCall');
    }
  }
};

// 监听用户状态
const handleUserStatus = (message) => {
  const { userId, status } = message;

  // 更新联系人状态
  const contact = contactList.value.find(c => c.id == userId);
  if (contact) contact.status = status;

  // 更新聊天列表状态
  const chat = chatList.value.find(c => c.id == userId);
  if (chat) chat.status = status;
};

const handleAllUserStatus = (message) => {
  const { users } = message;
   // 更新联系人列表状态
   contactList.value.forEach(contact => {
    if (users[contact.id] != undefined) {
      contact.status = users[contact.id];
    }
  });

  // 更新聊天列表状态
  chatList.value.forEach(chat => {
    if (users[chat.id] != undefined) {
      chat.status = users[chat.id];
    }
  });
};

// 发送消息
const sendWebSocketMessage = (message) => {
  return new Promise((resolve, reject) => {
    if (!socket.value || !isConnected.value) {
      // 尝试立即重连一次
      if (reconnectAttempts.value == 0) {
        initWebSocket();
        setTimeout(() => {
          if (isConnected.value) {
            socket.value.send(JSON.stringify(message));
            resolve();
          } else {
            reject(new Error("连接未就绪，请检查网络后重试"));
          }
        }, 500);
      } else {
        reject(new Error("连接已断开，正在尝试重新连接..."));
      }
      return;
    }

    try {
      socket.value.send(JSON.stringify(message));
      resolve();
    } catch (error) {
      console.error("发送消息失败:", error);
      reject(new Error("发送失败，请重试"));
    }
  });
};

// 消息发送处理
const handleSendMessage = async (message) => {
  if (!activeChatId.value) return;

  const chat = chatList.value.find(c => c.id == activeChatId.value);
  if (!chat) return;

  // 添加到本地聊天记录
  const tempMessage = {
    ...message,
    id: `temp-${Date.now()}`,
    isMe: true,
    time: new Date(),
    status: 'sending'
  };
  chat.messages.push(tempMessage);

  //构造发送消息
  const messageData = {
    type: "single",
    toId: activeChatId.value,
    messageType: message.type,
    content: message.content,
    fromId: userStore.userInfo.id
  };

  // 添加额外字段
  if (message.type == 'file') {
    messageData.fileName = message.fileName;
    messageData.fileSize = message.fileSize;
  } else if (message.type == 'audio') {
    messageData.duration = message.duration;
  }

  try {
    const res = await sendMessage(messageData);
    tempMessage.status = 'sent';
    tempMessage.time = new Date(res.createTime)
    tempMessage.id = res.messageId
  } catch (error) {
    console.error("发送消息失败:", error);
    tempMessage.status = 'failed';
    ElMessage.error(error.message);

    // 5秒后自动重试
    setTimeout(() => {
      if (tempMessage.status == 'failed') {
        handleSendMessage(message);
      }
    }, 5000);
  }
};

const handleStartCall = (type) => {
  if (!activeChatId.value) {
    ElMessage.warning("请先选择聊天对象");
    return;
  }

  const chat = chatList.value.find(c => c.id == activeChatId.value);
  if (!chat) return;

  ElMessageBox.confirm(
    `确定要发起${type == 'video' ? '视频' : '语音'}通话吗?`,
    "发起通话",
    {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "info",
    }
  ).then(() => {
    showCall.value = true;
    callType.value = type;
    callWith.value = chat.name;
    isCaller.value = true;

    // 发送通话请求
    sendWebSocketMessage({
      type: "call",
      toId: activeChatId.value,
      callType: type
    });

    // 不在此处添加通话记录
  });
};

const handleEndCall = ({ duration, isActiveEnd }) => {
  // 如果是主动挂断，发送通知给对方
  if (isActiveEnd && callWith.value) {
    sendWebSocketMessage({
      type: "call_end",
      toId: callWith.value,
      callType: callType.value,
      duration: duration || 0
    })
  }

  // 记录通话消息（只在主动挂断或收到结束通知时记录一次）
  if ((isActiveEnd || duration > 0) && activeChatId.value) {
    const chat = chatList.value.find(c => c.id == activeChatId.value)
    if (chat) {
      // 检查是否已存在相同通话记录
      const existingCall = chat.messages.find(
        msg => msg.type === 'call' &&
          msg.callType === callType.value &&
          Math.abs(new Date(msg.time) - new Date()) < 1000
      )

      if (!existingCall) {
        chat.messages.push({
          id: `call-end-${Date.now()}`,
          isMe: isActiveEnd,
          type: 'call',
          callType: callType.value,
          duration: duration,
          time: new Date(),
          status: duration > 0 ? 'ended' : 'missed'
        })
      }
    }
  }

  // 重置通话状态
  showCall.value = false
  callType.value = ""
  callWith.value = ""
  isCaller.value = false
}

// 监听状态变化
watch([showCall, callType, callWith, isCaller], () => {
  saveCallState();
});


// 初始化数据
const initData = async () => {
  try {
    // 获取联系人列表
    const userId = userStore.userInfo?.id;
    if (userId) {
      const res = await getFriends({ userId });
      contactList.value = res.map(item => ({
        ...item,
        status: "offline"
      }));
    }
  } catch (error) {
    ElMessage.error("初始化数据失败");
    console.error(error);
  }
};

const loadHistoryMessages = async (chatId) => {
  try {
    const userId = userStore.userInfo?.id;
    if (!userId || !chatId) return;

    const res = await getChatHistory({ formId: userId, toId: chatId, pageNum: 1, pageSize: 20 }); // 获取第一页，每页20条
    if (res) {
      const chat = chatList.value.find(c => c.id == chatId);
      if (chat) {
        // 确保API返回的数据是按时间降序排列的
        const sortedMessages = res.sort((a, b) => new Date(a.createTime) - new Date(b.createTime));

        // 使用 Set 去重已有消息
        const existingIds = new Set(chat.messages.map(m => m.id));
        const uniqueMessages = res
          .map(msg => ({
            ...msg,
            id: `msg-${msg.id}`,
            isMe: msg.fromId == userId,
            time: new Date(msg.createTime),
            status: 'sent'
          }))
          .filter(msg => !existingIds.has(msg.id));

        // 插入到聊天记录头部
        chat.messages = [...uniqueMessages, ...chat.messages];
      }
    }
  } catch (error) {
    console.error("加载历史消息失败:", error);
    ElMessage.error("加载历史消息失败");
  }
};

const handleBeforeUnload = (e) => {
  if (showCall.value) {
    e.preventDefault();
    e.returnValue = '您正在进行通话，确定要离开吗？';
  }
};

onMounted(() => {
  initData();
  initWebSocket();

  restoreCallState();

  // 监听页面刷新前事件
  window.addEventListener('beforeunload', handleBeforeUnload);
});

onUnmounted(() => {
  window.removeEventListener('beforeunload', handleBeforeUnload);
  if (socket.value) {
    socket.value.close();
  }
  stopHeartbeat();
});
</script>

<style scoped>
.deepchat-container-box {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 80vw;
  height: 80vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #fff;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
  border-radius: 12px;
  overflow: hidden;
  z-index: 1000;
}

.deepchat-container {
  display: flex;
  height: 100%;
  width: 100%;
}

.sidebar {
  width: 80px;
  height: 100%;
  background-color: #1890ff;
}

.list-container {
  width: 240px;
  border-right: 1px solid #e6e6e6;
  height: 100%;
}

.chat-container {
  flex: 1;
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.empty-chat {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
}

.contact-header {
  padding: 10px 0;
}

.contact-detail {
  display: flex;
}

.contact-info {
  width: 100%;
  padding: 14px;
}

.el-row {
  line-height: 28px;
}

.contact-actions {
  text-align: center;
  margin-top: 24px
}
</style>